/* $Id: AbstractScoreEntry.java 134 2011-08-27 16:48:38Z altdotua@gmail.com $ */

package alt.djudge.frontend.server.datatypes.scores;

import java.io.Serializable;
import java.util.Date;

import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.Inheritance;
import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.PrimaryKey;

import alt.djudge.frontend.server.datatypes.AbstractEntry;
import alt.djudge.frontend.server.datatypes.SubmissionEntry;


@PersistenceCapable(detachable="true")
@Inheritance(customStrategy = "complete-table")
public abstract class AbstractScoreEntry extends AbstractEntry implements Serializable, AbstractScoreInterface
{
	private static final long serialVersionUID = 1L;

	@PrimaryKey
	@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
	protected Long id;
	
	@Override
	public Long getId()
	{
		return id;
	}
	
	@Override
	public void setId(Long id)
	{
		this.id = id;
	}
	
	@Persistent
	protected Integer acceptedCount = 0;
	
	@Persistent
	protected Integer rejectedCount = 0;
	
	@Persistent
	protected Integer rejectedBeforeAcceptedCount = 0;
	
	@Persistent
	protected Integer pendingCount = 0;
	
	@Persistent
	protected Integer activeCount = 0;

	@Persistent
	protected Integer uniqueAcceptedCount = 0;

	@Persistent
	protected Integer uniqueRejectedCount = 0;

	@Persistent
	protected Date lastAcceptedDate;
	
	@Persistent
	protected Long lastAcceptedTime = 0L;
	
	@Persistent
	protected Date lastSubmittedDate;
	
	@Persistent
	protected Long lastSubmittedTime = 0L;
	
	@Persistent
	protected Long totalTime = 0L;
	
	@Persistent
	protected Integer totalScore = 0;
	
	@Persistent
	protected Boolean virtual = false;
	
	public AbstractScoreEntry()
	{
		prepareForRejudge();
	}
	
	@Override
	public void setAcceptedCount(Integer acceptedCount)
	{
		this.acceptedCount = acceptedCount;
	}

	@Override
	public Integer getAcceptedCount()
	{
		return acceptedCount;
	}

	@Override
	public void setRejectedCount(Integer rejectedCount)
	{
		this.rejectedCount = rejectedCount;
	}

	@Override
	public Integer getRejectedCount()
	{
		return rejectedCount;
	}

	@Override
	public void setPendingCount(Integer pendingCount)
	{
		this.pendingCount = pendingCount;
	}

	@Override
	public Integer getPendingCount()
	{
		return pendingCount;
	}

	@Override
	public void setActiveCount(Integer activeCount)
	{
		this.activeCount = activeCount;
	}

	@Override
	public Integer getActiveCount()
	{
		return activeCount;
	}

	@Override
	public void setUniqueAcceptedCount(Integer uniqueAcceptedCount)
	{
		this.uniqueAcceptedCount = uniqueAcceptedCount;
	}

	@Override
	public Integer getUniqueAcceptedCount()
	{
		return 0;
		//return uniqueAcceptedCount;
	}

	@Override
	public void setUniqueRejectedCount(Integer uniqueRejuctedCount)
	{
		this.uniqueRejectedCount = uniqueRejuctedCount;
	}

	@Override
	public Integer getUniqueRejectedCount()
	{
		return uniqueRejectedCount;
	}

	@Override
	public void setLastAcceptedDate(Date lastAcceptedDate)
	{
		this.lastAcceptedDate = lastAcceptedDate;
	}

	@Override
	public Date getLastAcceptedDate()
	{
		return lastAcceptedDate;
	}

	@Override
	public void setLastAcceptedTime(Long lastAcceptedTime)
	{
		this.lastAcceptedTime = lastAcceptedTime;
	}

	@Override
	public Long getLastAcceptedTime()
	{
		return lastAcceptedTime;
	}

	@Override
	public void setLastSubmittedDate(Date lastSubmittedDate)
	{
		this.lastSubmittedDate = lastSubmittedDate;
	}

	@Override
	public Date getLastSubmittedDate()
	{
		return lastSubmittedDate;
	}

	@Override
	public void setLastSubmittedTime(Long lastSubmittedTime)
	{
		this.lastSubmittedTime = lastSubmittedTime;
	}

	@Override
	public Long getLastSubmittedTime()
	{
		return lastSubmittedTime;
	}

	@Override
	public void prepareForRejudge()
	{
		acceptedCount = 0;
		activeCount = 0;
		lastAcceptedDate = null;
		lastAcceptedTime = 0L;
		lastSubmittedDate = null;
		lastSubmittedTime = 0L;
		pendingCount = 0;
		rejectedCount = 0;
		uniqueAcceptedCount = 0;
		uniqueRejectedCount = 0;
	}

	@Override
	public void decrementPendingCount()
	{
		pendingCount--;
	}

	@Override
	public void incrementPendingCount()
	{
		pendingCount++;
	}

	@Override
	public void incrementActiveCount()
	{
		activeCount++;
	}

	@Override
	public void incrementAcceptedCount()
	{
		acceptedCount++;
	}

	@Override
	public void incrementRejectedCount()
	{
		rejectedCount++;
	}

	@Override
	public void incrementUniqueAcceptedCount()
	{
		uniqueAcceptedCount++;
	}

	@Override
	public void incrementUniqueRejectedCount()
	{
		uniqueRejectedCount++;
	}
	
	@Override
	public String toString()
	{
		return acceptedCount + " " + rejectedCount;
	}

	public void setRejectedBeforeAcceptedCount(
			Integer rejectedBeforeAcceptedCount)
	{
		this.rejectedBeforeAcceptedCount = rejectedBeforeAcceptedCount;
	}

	public Integer getRejectedBeforeAcceptedCount()
	{
		return rejectedBeforeAcceptedCount;
	}
	
	public Long getTotalTime()
	{
		return totalTime;
	}
	
	public Long getTotalTimePen()
	{
		return getTotalTime() + 20 * getRejectedBeforeAcceptedCount();
	}
	
	public void setTotalTime(Long totalTime)
	{
		this.totalTime = totalTime;
	}

	@Override
	public Integer getTotalScore()
	{
		return totalScore;
	}

	@Override
	public void setTotalScore(int score)
	{
		this.totalScore = score;
	}

	@Override
	public Boolean getVirtual()
	{
		return virtual;
	}

	@Override
	public void setVirtual(Boolean virtualFlag)
	{
		virtual = virtualFlag; 
	}

	public void addSubmission(SubmissionEntry s)
	{
		if (s.isPending())
			pendingCount++;
		else if ("CE".equalsIgnoreCase(s.getJudgement()))
		{
			
		}
		else
		{
			activeCount++;
			lastSubmittedDate = s.getSubmissionTime();
			lastSubmittedTime = s.getContestTime();
			if (s.isAccepted())
			{
				if (acceptedCount == 0)
				{
					uniqueAcceptedCount++;
					rejectedBeforeAcceptedCount = rejectedCount;
					totalTime += rejectedBeforeAcceptedCount * 20 * 60 + s.getContestTime();
				}
				acceptedCount++;
				lastAcceptedDate = s.getSubmissionTime();
				lastAcceptedTime = s.getContestTime();
			}
			else
			{
				if (acceptedCount == 0)
					uniqueRejectedCount++;
				rejectedCount++;
			}
		}
	}
}
